/* eslint-disable @typescript-eslint/no-use-before-define */
import RNFS from 'react-native-fs';
import { DeviceEventEmitter } from 'react-native';
import { values, find, filter, reverse, propEq } from 'ramda';

import {
  VIDEO_TYPE_DESC,
  DOWNLOAD_PATH,
  DOWNLOAD_VIDEO_TASK_SUCCESS,
  DOWNLOAD_VIDEO_TASK_START,
  DOWNLOAD_VIDEO_TASK_PROGRESS,
  DOWNLOAD_VIDEO_TASK_DELETE,
  DOWNLOAD_VIDEO_TASK_PAUSE,
  DOWNLOAD_VIDEO_TASK_FAIL,
  DOWNLOAD_MANAGE_TAG,
  DOWNLOAD_VIDEO_TASK_CAN_PLAY,
  DOWNLOAD_VIDEO_TASK_INIT_CAN_PLAY,
  INIT_CAN_PLAY_TS_NUM,
  INIT_CAN_PLAY_PROGRESS
} from './constant';
import VideoDownloadTask from './videoDownloadTask';
import {
  DownloadVideoTask,
  InitVideoTasksProps,
  DownloadVideoTaskProps,
  InitVideoTaskProps
} from './types';
import {
  deleteAllStoreVideoTasks,
  deleteStoreVideoTask,
  getAllStoreVideoTasks,
  getFinishedStoreVideoTasks,
  getLatestStoreVideoTask,
  getStoreVideoTask,
  getUnFinishedStoreVideoTasks,
  getVideoTasksByParentId,
  setStoreVideoTask,
  unshiftStoreVideoTaskQueue
} from './videoDownloadStore';
import Log from '../../common/log';

let downloadVideoTask: DownloadVideoTask | null;

export const getCurrentDownloadVideoTask = (): DownloadVideoTask | null =>
  downloadVideoTask;

// 移除当前下载任务对象
export const removeDownloadVideoTask = (): void => {
  downloadVideoTask = null;
};

const onSuccess = (data: DownloadVideoTaskProps): void => {
  DeviceEventEmitter.emit(DOWNLOAD_VIDEO_TASK_SUCCESS, { ...data });
  // 设置store
  setStoreVideoTask(data);
  // 移除当前task对象
  removeDownloadVideoTask();
  // 继续下载
  continueDownload();
};
const onProgress = (data: DownloadVideoTaskProps): void => {
  // 设置store
  setStoreVideoTask(data);
  DeviceEventEmitter.emit(DOWNLOAD_VIDEO_TASK_PROGRESS, {
    ...data
  });
};
const onDelete = (data: DownloadVideoTaskProps): void => {
  // 删除store
  deleteStoreVideoTask(data.id);
  // 移除当前task对象
  removeDownloadVideoTask();
  setTimeout((): void => {
    // 继续下载
    continueDownload();
    DeviceEventEmitter.emit(DOWNLOAD_VIDEO_TASK_DELETE, {
      ...data
    });
  }, 100);
};
const onStart = (data: DownloadVideoTaskProps): void => {
  // 设置store
  setStoreVideoTask(data);
  DeviceEventEmitter.emit(DOWNLOAD_VIDEO_TASK_START, { ...data });
};
const onPause = (data: DownloadVideoTaskProps): void => {
  // 设置store
  setStoreVideoTask(data);
  // 移除当前task对象
  removeDownloadVideoTask();
  setTimeout((): void => {
    // 继续下载
    continueDownload();
    DeviceEventEmitter.emit(DOWNLOAD_VIDEO_TASK_PAUSE, {
      ...data
    });
  }, 200);
};
const onFail = (data: DownloadVideoTaskProps): void => {
  // 设置store
  setStoreVideoTask(data);
  // 移除当前task对象
  removeDownloadVideoTask();
  // 整个parentId下全部视为失败
  failDownloadByParentId(data.parentId);
  DeviceEventEmitter.emit(DOWNLOAD_VIDEO_TASK_FAIL, { ...data });
  setTimeout((): void => {
    // 继续下载
    continueDownload();
  }, 200);
};
const onTsListChanged = (data: DownloadVideoTaskProps): void => {
  // 设置store
  setStoreVideoTask(data);
};
const onCanPlay = (data: DownloadVideoTaskProps): void => {
  DeviceEventEmitter.emit(DOWNLOAD_VIDEO_TASK_CAN_PLAY, { ...data });
};
const onInitCanPlay = (data: DownloadVideoTaskProps): void => {
  DeviceEventEmitter.emit(DOWNLOAD_VIDEO_TASK_INIT_CAN_PLAY, { ...data });
};

// 初始化多个视频下载任务
export const initDownloadVideoTasks = (props: InitVideoTasksProps): void => {
  const { initVideoTasks, isPrior } = props;

  // 存缓存
  initVideoTasks.forEach((item): void => {
    const { parentId, parentTitle, id, title, type, urls, size, source } = item;
    const store = getStoreVideoTask(id);
    const init = isPrior ? unshiftStoreVideoTaskQueue : setStoreVideoTask;

    // 如果是需要立刻下载的话不过滤已有下载项，直接覆盖
    if ((!store && !isPrior) || isPrior) {
      init({
        id,
        title,
        type,
        urls,
        size,
        progress: 0,
        indexHaveDone: new Array(urls.length).fill(false),
        keyHaveDone: new Array(urls.length).fill(false),
        m3u8Paths: new Array(urls.length).fill(''),
        parentId,
        parentTitle,
        isPaused: false,
        isFailed: false,
        startTime: '',
        source,
        tsDoneNum: 0
      });
    }
  });

  // 如果是需要立刻下载的话，由于下载视频数组反转了，因此取最后一位开始下载
  const downloadStore = getStoreVideoTask(
    initVideoTasks[isPrior ? initVideoTasks.length - 1 : 0].id
  );

  Log.i(
    DOWNLOAD_MANAGE_TAG,
    JSON.stringify({
      event: 'initDownloadVideoTasks-start',
      downloadVideoTask,
      downloadStore
    })
  );

  if (!downloadVideoTask && downloadStore) {
    // 取最近的下载任务;
    downloadVideoTask = VideoDownloadTask.initDownloadVideoTask({
      ...downloadStore,
      onSuccess,
      onProgress,
      onDelete,
      onStart,
      onPause,
      onFail,
      onTsListChanged,
      onCanPlay,
      onInitCanPlay
    });
    downloadVideoTask.start();
  }
};

// 初始化一个视频下载任务
export const initDownloadVideoTask = (props: InitVideoTaskProps): void => {
  const {
    parentId,
    parentTitle,
    id,
    title,
    type,
    urls,
    size,
    source,
    ignoreTsList
  } = props;

  const store = getStoreVideoTask(id);
  const init = setStoreVideoTask;

  Log.i(
    DOWNLOAD_MANAGE_TAG,
    JSON.stringify({
      event: 'initDownloadVideoTask-store',
      store
    })
  );

  if (!store) {
    init({
      id,
      title,
      type,
      urls,
      size,
      progress: 0,
      indexHaveDone: new Array(urls.length).fill(false),
      keyHaveDone: new Array(urls.length).fill(false),
      m3u8Paths: new Array(urls.length).fill(''),
      parentId,
      parentTitle,
      isPaused: false,
      isFailed: false,
      startTime: '',
      source,
      tsDoneNum: 0
    });
  }
  const downloadStore = getStoreVideoTask(id);

  Log.i(
    DOWNLOAD_MANAGE_TAG,
    JSON.stringify({
      event: 'initDownloadVideoTask-start',
      downloadVideoTask,
      downloadStore
    })
  );

  if (!downloadVideoTask && downloadStore) {
    // 取最近的下载任务
    downloadVideoTask = VideoDownloadTask.initDownloadVideoTask({
      ...downloadStore,
      ignoreTsList,
      onSuccess,
      onProgress,
      onDelete,
      onStart,
      onPause,
      onFail,
      onTsListChanged,
      onCanPlay,
      onInitCanPlay
    });
    downloadVideoTask.start();
  }
};

// 暂停当前下载任务对象
export const pauseDownloadVideoTask = (): void => {
  if (downloadVideoTask) {
    downloadVideoTask.pause();
  }
};

// 删除当前下载任务对象
export const deleteDownloadVideoTask = (): void => {
  if (downloadVideoTask) {
    downloadVideoTask.delete();
  }
};

// 删除指定目录下的文件
export const deleteOtherVideoTaskFile = (folderName: string): void => {
  RNFS.unlink(`${DOWNLOAD_PATH}/${folderName}`);
};

// 删除全部下载文件
export const deleteAllVideoTasksFile = (): void => {
  RNFS.unlink(DOWNLOAD_PATH);
};

// 继续下载下一个任务
export const continueDownload = (ignoreTsList: string[] = []): void => {
  setTimeout((): void => {
    const latestVideoTask = getLatestStoreVideoTask();
    Log.i(
      DOWNLOAD_MANAGE_TAG,
      JSON.stringify({
        event: 'continueDownload',
        latestVideoTask
      })
    );
    if (latestVideoTask) {
      initDownloadVideoTask({
        ...latestVideoTask,
        ignoreTsList
      });
    }
  }, 100);
};

// 开始某个视频下载任务
export const startDownload = (id: number | string): void => {
  const videoTask = getStoreVideoTask(id);
  Log.i(
    DOWNLOAD_MANAGE_TAG,
    JSON.stringify({
      event: 'startDownload',
      videoTask
    })
  );
  if (videoTask) {
    initDownloadVideoTask({
      ...videoTask
    });
  }
};

// 删除某个视频下载任务
export const deleteOtherVideoTask = (id: number | string): void => {
  const videoTask = getStoreVideoTask(id);
  if (videoTask) {
    const { parentId, type, urls } = videoTask;
    urls.forEach((url): void => {
      const [serverDir] = url.split(`/${VIDEO_TYPE_DESC[type]}`);
      const dirArray = serverDir.split('/');
      const folderName = `${parentId}/${dirArray[dirArray.length - 1]}`;
      deleteOtherVideoTaskFile(folderName);
    });
  }
  deleteStoreVideoTask(id);
};

// 删除全部下载任务
export const deleteAllVideoTasks = (): void => {
  removeDownloadVideoTask();
  deleteAllVideoTasksFile();
  deleteAllStoreVideoTasks();
};

// 开始全部下载任务
export const startDownloadAllVideoTasks = (): void => {
  const tasks = getUnFinishedStoreVideoTasks();
  tasks.forEach((item): void =>
    setStoreVideoTask({ ...item, isPaused: false, isFailed: false })
  );
  continueDownload();
};

// 暂停某个下载任务
export const pauseOtherVideoTask = (id: number): void => {
  const videoTask = getStoreVideoTask(id);
  if (videoTask) {
    setStoreVideoTask({ ...videoTask, isPaused: true });
  }
};

// 暂停全部下载任务
export const pauseAllVideoTasks = (): void => {
  pauseDownloadVideoTask();
  const tasks = getUnFinishedStoreVideoTasks();
  tasks.forEach((item): void => setStoreVideoTask({ ...item, isPaused: true }));
};

// 判断某个下载任务是否下载完成
export const getVideoTaskIsFinished = (
  task: DownloadVideoTaskProps
): boolean => {
  const { indexHaveDone, keyHaveDone, progress } = task;
  const allIndexHaveDone = indexHaveDone.every((item): boolean => item);
  const allKeyHaveDone = keyHaveDone.every((item): boolean => item);
  return allIndexHaveDone && allKeyHaveDone && progress >= 1;
};

// 过滤已经不需要的下载任务并删除
export const filterExcludeVideoTasks = (tasks: InitVideoTaskProps[]): void => {
  if (tasks.length > 0) {
    const { parentId } = tasks[0];
    const allTasks = values(getVideoTasksByParentId(parentId));

    const filterTasks = (item: DownloadVideoTaskProps): boolean =>
      !find((task): boolean => item.id === task.id, allTasks);

    const excludeTasks = filter(filterTasks)(allTasks);

    excludeTasks.forEach((item): void => {
      deleteOtherVideoTask(item.id);
    });
  }
};

// 初始化多个下载任务
export const startInitDownloadVideoTasks = (
  tasks: InitVideoTaskProps[],
  isPrior = false
): void => {
  const finshedVideoTasks = getFinishedStoreVideoTasks();

  const filterFinishedVideoTasks = (item: InitVideoTaskProps): boolean => {
    for (let i = 0; i < finshedVideoTasks.length; i += 1) {
      if (finshedVideoTasks[i].id === item.id) {
        return false;
      }
    }
    return true;
  };

  // 过滤已下载的文件
  const needDownloadVideoTasks = filter(filterFinishedVideoTasks)(tasks);

  Log.i(
    DOWNLOAD_MANAGE_TAG,
    JSON.stringify({
      event: 'startInitDownloadVideoTasks',
      needDownloadVideoTasks
    })
  );

  if (needDownloadVideoTasks.length) {
    initDownloadVideoTasks({
      initVideoTasks: isPrior
        ? reverse(needDownloadVideoTasks)
        : needDownloadVideoTasks, // 如果是需要立刻下载的需要反转数组
      isPrior
    });
  }
};

// 开始某一parentId下的视频下载任务
export const startDownloadByParentId = (parentId: number): void => {
  const tasks = getUnFinishedStoreVideoTasks();
  const parentTasks = filter(propEq('parentId', parentId))(tasks);
  parentTasks.forEach((item: DownloadVideoTaskProps): void =>
    setStoreVideoTask({ ...item, isPaused: false, isFailed: false })
  );
  Log.i(
    DOWNLOAD_MANAGE_TAG,
    JSON.stringify({
      event: 'startDownloadByParentId',
      parentId,
      parentTasks
    })
  );
  continueDownload();
};

// 暂停某一parentId下的视频下载任务
export const pauseDownloadByParentId = (parentId: number): void => {
  const downloadingVideoTask = getCurrentDownloadVideoTask();

  if (downloadingVideoTask && downloadingVideoTask.parentId === parentId) {
    pauseDownloadVideoTask();
  }
  const tasks = getUnFinishedStoreVideoTasks();
  const parentTasks = filter(propEq('parentId', parentId))(tasks);
  parentTasks.forEach((item: DownloadVideoTaskProps): void =>
    setStoreVideoTask({ ...item, isPaused: true })
  );
};

// 删除某一parentId下的视频下载任务
export const deleteDownloadByParentId = (parentId: number): void => {
  const allTasks = getAllStoreVideoTasks();
  const parentTasks = filter(propEq('parentId', parentId))(allTasks);
  // 在删除时，少数情况会有个别文件下载完成，为防止触发onProgess回调，先将要删除的任务暂停
  parentTasks.forEach((item: DownloadVideoTaskProps): void =>
    setStoreVideoTask({ ...item, isPaused: true })
  );
  const downloadingVideoTask = getCurrentDownloadVideoTask();

  if (downloadingVideoTask && downloadingVideoTask.parentId === parentId) {
    deleteDownloadVideoTask();
  }
  parentTasks.forEach((item: DownloadVideoTaskProps): void => {
    deleteOtherVideoTask(item.id);
  });
};

// 某一parentId下的视频下载任务失败
export const failDownloadByParentId = (parentId: number): void => {
  const downloadingVideoTask = getCurrentDownloadVideoTask();

  if (downloadingVideoTask && downloadingVideoTask.parentId === parentId) {
    pauseDownloadVideoTask();
  }
  const tasks = getUnFinishedStoreVideoTasks();
  const parentTasks = filter(propEq('parentId', parentId))(tasks);
  parentTasks.forEach((item: DownloadVideoTaskProps): void =>
    setStoreVideoTask({ ...item, isFailed: true })
  );
};

// 设置当前下载任务可忽略的ts文件
export const setVideoTaskIgnoreTsList = (ignoreTsList: string[]): void => {
  if (downloadVideoTask) {
    downloadVideoTask.setIgnoreTsList(ignoreTsList);
  }
};

// 设置某项未开始的任务暂停，即跳过部分任务的下载
export const setUnStartVideoTaskPaused = (id: number | string): void => {
  const task = getStoreVideoTask(id);
  Log.i(
    DOWNLOAD_MANAGE_TAG,
    JSON.stringify({
      event: 'setUnStartVideoTaskPaused',
      task
    })
  );
  if (task) {
    setStoreVideoTask({ ...task, isPaused: true });
  }
};

// 设置某项未开始的任务开始，即恢复部分任务的下载
export const setUnStartVideoTaskDownload = (id: number | string): void => {
  const task = getStoreVideoTask(id);
  Log.i(
    DOWNLOAD_MANAGE_TAG,
    JSON.stringify({
      event: 'setUnStartVideoTaskDownload',
      task
    })
  );
  if (task && task.progress < 1) {
    setStoreVideoTask({ ...task, isPaused: false });
  }
};

// 初始化加载资源时认为资源可播放
export const getVideoTaskCanPlay = (task: DownloadVideoTaskProps): boolean => {
  return (
    task.tsDoneNum >= INIT_CAN_PLAY_TS_NUM ||
    task.progress >= INIT_CAN_PLAY_PROGRESS
  );
};
